package com.ktwlsoft.fundmanage.fundFlow.service;

import com.ktwlsoft.fundmanage.domain.entity.FundInRecord;
import com.ktwlsoft.fundmanage.domain.entity.FundOutRecord;
import com.ktwlsoft.fundmanage.domain.entity.FundSuperviseAccept;
import com.ktwlsoft.fundmanage.domain.entity.TransferApply;
import com.ktwlsoft.fundmanage.domain.entity.TransferApply.State;
import com.ktwlsoft.fundmanage.domain.repository.FundInRecordRepository;
import com.ktwlsoft.fundmanage.domain.repository.FundOutRecordRepository;
import com.ktwlsoft.fundmanage.domain.repository.FundSuperviseAcceptRepository;
import com.ktwlsoft.fundmanage.domain.repository.TransferApplyRepository;
import com.ktwlsoft.fundmanage.payload.BaseResult;
import com.ktwlsoft.fundmanage.payload.IAccountUser;
import com.ktwlsoft.fundmanage.payload.ResultType;
import com.ktwlsoft.fundmanage.payload.exceptions.BusinessError;
import com.ktwlsoft.fundmanage.payload.exceptions.FlowTaskMoreOrNoneException;
import com.ktwlsoft.fundmanage.payload.fundOut.FundOutCheckRequest;
import com.ktwlsoft.fundmanage.payload.fundOut.FundOutOrCancelRequest;
import com.ktwlsoft.fundmanage.payload.fundOut.TransferApprovalBatchRequest;
import com.ktwlsoft.fundmanage.service.CandidateService;
import com.ktwlsoft.fundmanage.utils.UserUtils;
import org.activiti.engine.*;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FundOutFlowService extends BaseFlow {

    private final TransferApplyRepository transferApplyRepository;

    private final FundSuperviseAcceptRepository fundSuperviseAcceptRepository;

    private final FundOutRecordRepository fundOutRecordRepository;

    private final FundInRecordRepository fundInRecordRepository;

    protected FundOutFlowService(CandidateService candidate, RuntimeService runtimeService, TaskService taskService, ProcessEngine processEngine, FormService formService, RepositoryService repositoryService, TransferApplyRepository transferApplyRepository, FundSuperviseAcceptRepository fundSuperviseAcceptRepository, FundOutRecordRepository fundOutRecordRepository, FundInRecordRepository fundInRecordRepository) {
        super(candidate, runtimeService, taskService, processEngine, formService, repositoryService);
        this.transferApplyRepository = transferApplyRepository;
        this.fundSuperviseAcceptRepository = fundSuperviseAcceptRepository;
        this.fundOutRecordRepository = fundOutRecordRepository;
        this.fundInRecordRepository = fundInRecordRepository;
    }

    @PostConstruct
    public void init() {
        repositoryService.createDeployment()
                .addClasspathResource("processes/Fund_out.bpmn20.xml")
                .deploy();
    }

    @Transactional(rollbackOn = Exception.class)
    public BaseResult<?> completeTaskBatch(TransferApprovalBatchRequest requests, List<String> roles) {
        try {
            IAccountUser user = UserUtils.getUser();
            for (TransferApprovalBatchRequest.TransferApproval transferApproval : requests.getTransferApprovals()) {
                Task task = getTask("Transfer Approval", transferApproval.getInstanceId());
                TransferApply transferApply = transferApplyRepository.findById(transferApproval.getTransId()).orElse(null);

                if (transferApply == null) {
                    throw new BusinessError("划款单批量审核：未找到划款单");
                }
                Map<String, Object> variables = new HashMap<>();
                FundOutOrCancelRequest fundOutOrCancelRequest = new FundOutOrCancelRequest();
                fundOutOrCancelRequest.setRemark(transferApproval.getRemark());
                variables.put("fundOutOrCancelRequest",fundOutOrCancelRequest);
                variables.put("transId", transferApproval.getTransId());
                FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(requests.getTsCode());

                //以下if判断此次行为是作废划款单还是审核划款单
                if (requests.isCancel()) {//作废划款单
                    variables.put("transferApproval", "CANCEL");
                    //设置案件的退款单状态。
                    // if(transferApply.getTransferType() == TransferApply.TransferType.REFUND){
                    //     fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.WAIT_TRANSFER);
                    // }
                    fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.WAIT_TRANSFER);
                } else {
                    //审核划款单
                    transferApply.setAuthOperator(user.getName());
                    transferApply.setAuthOperatorId(user.getUserId());
                    transferApply.setAuthTime(new Date());
                    transferApply.setAuthRemark(transferApproval.getRemark());
                    // transferApply.setAuditState(requests.isApproval() ? TransferApply.AuditStatus.PASSED : TransferApply.AuditStatus.UNPASSED);
                    transferApplyRepository.save(transferApply);
                    if (requests.isApproval()) {
                        transferApply.setAuditState(TransferApply.AuditStatus.PASSED);
                        if(transferApply.getTransferType() == TransferApply.TransferType.REFUND){
                            fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.PASSED);
                        }
                        variables.put("transferApproval", "PASS");
//                        variables.put("transferType", transferApply.getTransferType());
//                        variables.put("transfer_prepare_refund", transferApply);
                    } else {
                        transferApply.setAuditState(TransferApply.AuditStatus.UNPASSED);
                        transferApply.setState(State.CANCEL);
                        if(transferApply.getTransferType() == TransferApply.TransferType.REFUND){
                            fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.UNPASSED);
                        }
                        variables.put("transferApproval", "UNPASS");
                    }
                }
                completeTask(task.getId(), variables);
            }
            return BaseResult.ok("Approval completed!");
        } catch (FlowTaskMoreOrNoneException ex) {
            return BaseResult.body(ex.getMessage(), ResultType.BUSINESS_ERROR);
        }
    }

    @Transactional(rollbackOn = Exception.class)
    public boolean forceCancelTransApply(long transferId) {
        TransferApply transferApply = transferApplyRepository.findById(transferId).orElse(null);
        if (transferApply == null) {
            throw new BusinessError("划款单为空！");
        }
        if(!fundOutRecordRepository.existsById(transferApply.getId())){
            throw new BusinessError("该划款单下有出账数据，不能撤销！");
        }
        if(fundInRecordRepository.restoreTransferedAmount(transferApply.getAmount(),transferApply.getFundInCode())==0){
            throw new BusinessError("未能撤销该划款单对应入账数据的已划款金额！");
        }
        transferApply.setState(TransferApply.State.CANCEL_HANDED);
        transferApply.setForceCancel(true);
        if(fundSuperviseAcceptRepository.addAmouteLeft(transferApply.getAmount(), transferApply.getTsCode())==0){
            throw new BusinessError("撤回失败，未能撤回该案件可划款金额！");
        }
        deleteTask(transferApply.getFlowInstanceId(), "USER FORCE TERMINATE THIS TASK");
        return true;
    }
}
